/*
 * Copyright (c) 2010 Sylvestre Gallon <syl@pmbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/types.h>
#include <sys/queue.h>
#include <objc.h>
#include <class.h>
#include <stdio.h>
#include <string.h>

#define HASH_SIZE ('z' - 'a' + 2)

struct class_hash_head class_hash[HASH_SIZE];

void
__objc_init_class_hash(void)
{
        int i;

        for (i = 0 ; i < HASH_SIZE ; i++) {
                TAILQ_INIT(&class_hash[i]);
        }
        return;
}

Class
objc_lookup_class(const char *name)
{
        return (objc_get_class(name));
}

Class 
objc_get_class(const char *name)
{
        struct class_hash *ch;
        Class ret;
	char c;
        int i;

        ret = NULL;
	c = name[0];
	if (c >= 'A' && c <= 'Z')
		i = c - 'A';
	else if (c >= 'a' && c <= 'z')
		i = c - 'a';
	else
		i = 'z' - 'a' + 1;

        TAILQ_FOREACH(ch, &class_hash[i], entry) {
                if (strcmp(ch->cl->name, name) == 0) {
                        ret = ch->cl;
                        break ;
                }
        }

        return ret;
}

void
__objc_add_class_in_hash(Class cl)
{
        struct class_hash *ch;
	char c;
        int i;

	c = cl->name[0];
	if (c >= 'A' && c <= 'Z')
		i = c - 'A';
	else if (c >= 'a' && c <= 'z')
		i = c - 'a';
	else
		i = 'z' - 'a' + 1;

        ch = __objc_malloc(sizeof(*ch));
        ch->cl = cl;
        TAILQ_INSERT_TAIL(&class_hash[i], ch, entry);
        return;
}

id
__objc_class_create_instance(Class cl)
{
        id n = nil;

        n = __objc_malloc(cl->instance_size);
        memset(n, 0, cl->instance_size);
        n->cl = cl;
        return n;
}

id
__objc_class_object_dispose(id obj)
{
        __objc_free(obj);
        return 0;
}
